﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EnvDTE;
using EnvDTE80;
using System.Text.RegularExpressions;

namespace SinacorRules
{
    public sealed class Rule_ParameterMethodCommunication : BaseAddIn.Rules.BaseRuleAddIn
    {
        #region Campos

        private Type _tipoBaseModel;
        private Type _tipoModelCollection;
        private Dictionary<string, bool> _isBaseCommunication;
        private List<String> exceptList;

        #endregion

        #region Constructor

        public Rule_ParameterMethodCommunication() :
            base("ParameterMethodCommunication", "SinacorRules.SinacorRules", typeof(Rule_ParameterMethodCommunication).Assembly)
        {
            _tipoBaseModel = typeof(Sinacor.Infra.UI.Common.BaseModel);
            _tipoModelCollection = typeof(Sinacor.Infra.UI.Common.ModelCollection<Sinacor.Infra.UI.Common.BaseModel>);

            exceptList = new List<String>();
            exceptList.Add("Empty");
            exceptList.Add("Object");
            exceptList.Add("DBNull");
        }

        #endregion

        #region Protected Override Methods

        protected sealed override void Before_IniciaAnalise()
        {
            _isBaseCommunication = new Dictionary<string, bool>();
        }


        protected sealed override void Check(CodeFunction funcao, CodeNamespace namespaceElement, CodeClass2 classe)
        {
			Regex r = new Regex(@"\Sinacor.UI\..+\.Communication[.+]?");
			if (r.IsMatch(classe.Namespace.Name))
			{
				CodeParameter parameter;
				CodeClass2 classeParametro;
				bool isValid = true;

				if (!_isBaseCommunication.ContainsKey(classe.FullName))
					_isBaseCommunication.Add(classe.FullName,
											 true);
				//Common.Rotinas.CheckClassInheritance(classe, typeof(Sinacor.Infra.UI.Common.BaseCommunication)));


				if (_isBaseCommunication[classe.FullName]
					 && funcao.FunctionKind == vsCMFunction.vsCMFunctionFunction)
				{
					for (int i = 1; i <= funcao.Parameters.Count; i++)
					{
						parameter = (CodeParameter)funcao.Parameters.Item(i);

						if (parameter.Type.TypeKind == vsCMTypeRef.vsCMTypeRefArray)
						{
							isValid = false;
						}
						else if (parameter.Type.CodeType.Kind == vsCMElement.vsCMElementClass)
						{
							classeParametro = (CodeClass2)parameter.Type.CodeType;
							if (!Common.Rotinas.CheckClassInheritance(classeParametro, _tipoBaseModel)
								&& !Common.Rotinas.CheckClassInheritance(classeParametro, _tipoModelCollection))
							{
								isValid = false;
							}
						}
						else if (parameter.Type.CodeType.Kind == vsCMElement.vsCMElementStruct
								 && (parameter.Type.TypeKind == vsCMTypeRef.vsCMTypeRefCodeType
									 || parameter.Type.TypeKind == vsCMTypeRef.vsCMTypeRefObject
									 || parameter.Type.TypeKind == vsCMTypeRef.vsCMTypeRefOther
									 || parameter.Type.TypeKind == vsCMTypeRef.vsCMTypeRefVoid
									 || parameter.Type.TypeKind == vsCMTypeRef.vsCMTypeRefVariant))
						{
							isValid = false;
						}

						if (!isValid)
						{
							GeraProblemaAddIn(parameter.StartPoint.Parent.Parent.FullName,
											  parameter.StartPoint.Line,
											  parameter.StartPoint.DisplayColumn,
											  "ParameterMethodCommunicationResolution",
											  classe.Name,
											  funcao.Name,
											  parameter.Name,
											  namespaceElement.Name);
							break;
						}
					}
				}
			}
        }

        #endregion
    }
}
